#include "base/channel.h"
#include "base/channelpool.h"
#include "base/log.h"

#include "base/epoll.h"
namespace net_tools::base
{

  Epoll::Epoll(int size, std::atomic<bool> *wakeup)
      : channelpool_(new Channelpool(this, size)),
        epollid_(epoll_create(2048)),
        wakeup_(wakeup),
        max_event_number_(size),
        last_time_triggered_(0)
  {
    epoll_event_.reserve(size);
  };
  void Epoll::Epoll_wait(int time_out)
  {
    wakeup_->store(false);
    last_time_triggered_ = epoll_wait(epollid_,
                                      &*epoll_event_.begin(),
                                      max_event_number_,
                                      time_out);
    wakeup_->store(true);
    for (int count = 0; count < last_time_triggered_; ++count)
    {
      reinterpret_cast<Channel *>(epoll_event_[count].data.ptr)
          ->Callback(epoll_event_[count].events);
    }
    if (last_time_triggered_ == max_event_number_) [[unlikely]]
    {
      max_event_number_ = max_event_number_ << 1;
      epoll_event_.reserve(max_event_number_);
    }
  };
  void Epoll::Add_event(Channel *channel_)
  {
    // NT_LOG_INFO << channel_ << NT_LOG_ENDL;
    epoll_ctl(epollid_, EPOLL_CTL_ADD, channel_->listenfd_, &channel_->event_);
  };
  void Epoll::Mod_event(Channel *channel_)
  {
    epoll_ctl(epollid_, EPOLL_CTL_MOD, channel_->listenfd_, &channel_->event_);
  };
  void Epoll::Del_event(Channel *channel_)
  {
    epoll_ctl(epollid_, EPOLL_CTL_DEL, channel_->listenfd_, &channel_->event_);
  };
  Channel *Epoll::Get_free_channel(int fd)
  {
    return channelpool_->Get_Channel(fd);
  };
  void Epoll::Free_channel(Channel *channel)
  {
    channelpool_->Free_Channel(channel);
  };

} // namespace net_tools::base